package com.tingyuge.thinking.spring.dependency.lookup;

import com.tingyuge.thinking.spring.ioc.overview.domain.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author xiaodao
 * @version 1.0
 * @date 2021/6/27
 */
public class TypeSafetyDependencyLookupDemo {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        //注册 configuration class（配置类）
        applicationContext.register(TypeSafetyDependencyLookupDemo.class);
        //启动应用上下文
        applicationContext.refresh();

        //演示beanFactory#getbean 方法的安全性
        displayBeanFactoryGetBean(applicationContext);
        //演示ObjectFactory#GetObject 方法的安全性
        displayObjectFactoryGetObject(applicationContext);
        ///演示ObjectFactory#IfAvailablet 方法的安全性
        displayObjectProviderIfAvailable(applicationContext);
        ///演示ListableBeanFactory#getBeansOfType 方法的安全性
        displayListableBeanFactory(applicationContext);
        //演示ObjectProvider#Stream 方法的安全性
        displayObjectProviderStreamOps(applicationContext);

        applicationContext.close();
    }

    private static void displayObjectProviderStreamOps(AnnotationConfigApplicationContext applicationContext) {
        ObjectProvider<String> beanProvider = applicationContext.getBeanProvider(String.class);
        printBeansException("displayListableBeanFactory", () -> beanProvider.forEach(System.out::println));
    }

    private static void displayListableBeanFactory(AnnotationConfigApplicationContext applicationContext) {
        DefaultListableBeanFactory listableBeanFactory = applicationContext.getDefaultListableBeanFactory();
        printBeansException("displayListableBeanFactory", () -> listableBeanFactory.getBeansOfType(User.class));
    }

    private static void displayObjectProviderIfAvailable(AnnotationConfigApplicationContext applicationContext) {
        ObjectProvider<User> beanProvider = applicationContext.getBeanProvider(User.class);
        printBeansException("displayObjectProviderIfAvailable", () -> beanProvider.getIfAvailable());
    }

    private static void displayObjectFactoryGetObject(AnnotationConfigApplicationContext applicationContext) {
//ObjectProvider<T> extends ObjectFactory
        ObjectProvider<User> beanProvider = applicationContext.getBeanProvider(User.class);
        printBeansException("displayObjectFactoryGetObject", () -> beanProvider.getObject());

    }

    public static void displayBeanFactoryGetBean(BeanFactory beanFactory) {

        printBeansException("displayBeanFactoryGetBean", () -> beanFactory.getBean(User.class));


    }

    private static void printBeansException(String source, Runnable runnable) {
        System.err.println("-----------------");
        System.err.println("Source from :  " + source);
        try {
            runnable.run();
        } catch (BeansException e) {
            e.printStackTrace();
        }
    }
}
